#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>
#include <vector>
#include <iostream>
template <class T>
#define NUM 16
class RingQueue
{
    
public:
    RingQueue(int cap = NUM) : cap_(cap),q(cap)
    {
        sem_init(&data_sem, 0, 0);     // data_sem信号 0线程间共享 0初始值
        sem_init(&space_sem, 0, cap_); // data_sem信号 0线程间共享 cap_初始值
        consume_step = 0;
        product_step = 0;
    }

    ~RingQueue()
    {
        sem_destroy(&data_sem);
        sem_destroy(&space_sem);
    }

    void PutData(const T &data)
    {
        sem_wait(&space_sem);
        q[consume_step] = data;
        consume_step++;
        consume_step %= cap_;
        sem_post(&data_sem);
    }

    void GetData(T &data)
    {
        sem_wait(&data_sem);
        data = q[product_step];
        product_step++;
        product_step %= cap_;
        sem_post(&space_sem);
    }

private:
    int cap_;
    std::vector<T> q;
    sem_t data_sem;
    sem_t space_sem;
    int consume_step;
    int product_step;
};
void *consumer(void *arg)
{
    RingQueue<int> *rqp = (RingQueue<int> *)arg;
    while (1)
    {
        int data;
        rqp->GetData(data);
        std::cout << "we get a data :" << data << std::endl;
    }
}
void *productor(void *arg)
{
    RingQueue<int> *rpq = (RingQueue<int> *)arg;
    srand((unsigned long)time(NULL));
    while (1)
    {
        int data = rand() % 1024;
        rpq->PutData(data);
        std::cout << "we put a data :" << data << std::endl;
    }
}
int main(void)
{
    pthread_t p,c;
    RingQueue<int> rq;

    pthread_create(&p,NULL,productor,(void*)&rq);
    pthread_create(&c,NULL,consumer,(void*)&rq);

    pthread_join(p,NULL);
    pthread_join(c,NULL);

    return 0;
}
